import base64
import random
import re
import smtplib
import time
from email.mime.text import MIMEText

from django.contrib.auth import login, authenticate, logout
from django.urls import reverse
from django.contrib.auth.mixins import LoginRequiredMixin
from django import http
from django.db import DatabaseError
from django.shortcuts import render, redirect

# Create your views here.
from django.views import View
from django.contrib import messages
from django_redis import get_redis_connection


from apps.users.models import User, Address
from apps.users.utils import isidcard
import pymongo

from libs.sms import send_codes


class RegisterView(View):
    """用户注册"""

    def get(self, request):
        """
        提供注册页面
        :param request:
        :return:
        """

        return render(request, 'register.html')

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        phone = request.POST.get('phone')

        count = User.objects.filter(username=username).count()
        if count == 1:
            messages.success(request, "用户名已注册，请重试")
            return render(request, 'register.html')

        count2 = User.objects.filter(mobile=phone).count()
        if count2 == 1:
            messages.success(request, "手机号已注册，请重试")
            return render(request, 'register.html')

        if not all([username, password, password2, phone]):
            messages.success(request, "请输入完整，请重试")
            return render(request, 'register.html')

        if not re.match(r'^[a-zA-Z0-9_]{5,20}$', username):
            messages.success(request, "请输入5-20个字符的用户名，请重试")
            return render(request, 'register.html')

        # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            messages.success(request, "请输入8-20个字符的数字，请重试")
            return render(request, 'register.html')

        # 判断密码是否一致
        if password != password2:
            messages.success(request, "两次密码不一致，请重试")
            return render(request, 'register.html')

        if not re.match(r'^1[3-9]\d{9}$', phone):
            messages.success(request, "手机号输入有误，请重试")
            return render(request, 'register.html')

        # 保存注册数据
        try:
            user = User.objects.create_user(username=username, password=password, mobile=phone)
        except DatabaseError:
            messages.success(request, "注册失败 请重试")
            return render(request, 'register.html')

        # 响应注册结果
        login(request, user)
        response = redirect(reverse('index:index'))
        # 注册时用户名写入到cookie，有效期15天
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)

        return response


class LoginView(View):
    def get(self, request):
        return render(request, "login.html")

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('password')
        jizhu = request.POST.get('jizhu')

        if not all([username, password]):
            messages.success(request, "请输入完整的账号密码")
            return render(request, 'login.html')

        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            messages.success(request, "账号在5-20位以内 请重新输入")
            return render(request, 'login.html')

        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            messages.success(request, "密码在8-20位， 请重新输入")
            return render(request, 'login.html')

        user = authenticate(username=username, password=password)
        if user is None:
            messages.success(request, "用户名或密码错误 请重试")
            return render(request, 'login.html')

        login(request, user)

        if jizhu != 1:
            request.session.set_expiry(0)
        else:
            request.session.set_expiry(None)
        response = redirect(reverse('index:index'))
        # 注册时用户名写入到cookie，有效期15天
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)

        return response


class LogoutView(View):

    def get(self, request):
        """实现退出登录逻辑"""
        # 清理session
        logout(request)

        # 退出登录，重定向到登录页
        response = redirect(reverse('index:index'))

        # 退出登录时清除cookie中的username
        response.delete_cookie('username')

        return response


class UserCenterView(LoginRequiredMixin, View):
    """用户中心"""

    def get(self, request):
        """提供个人信息界面"""
        fenshu = 20
        if request.user.mobile:
            fenshu += 20
        if request.user.email:
            fenshu += 20
        if request.user.Idverification == "1":
            fenshu += 10
        if request.user.Idverification == "2":
            fenshu += 20
        if request.user.Secret_protection == "1":
            fenshu += 20
        context = {
            'username': request.user.username,
            'mobile': request.user.mobile,
            'yanzheng': request.user.Idverification,
            'mibao': request.user.Secret_protection,
            'fenshu': fenshu,
            'phone': request.user.mobile,
            'email':request.user.email
        }
        return render(request, 'safety.html', context=context)


class UserPasswordView(LoginRequiredMixin, View):
    def get(self, request):

        return render(request, 'password.html')

    def post(self, request):
        old_password = request.POST.get('old_password')
        new_password1 = request.POST.get('new_password1')
        new_password2 = request.POST.get('new_password2')
        if not all([old_password, new_password1, new_password2]):
            messages.success(request, "请输入完整")
            return render(request, 'password.html')
        if not re.match(r'^[0-9A-Za-z]{8,20}$', new_password1):
            messages.success(request, "密码最少8位 最长20位")
            return render(request, 'password.html')
        if new_password1 != new_password2:
            messages.success(request, "两次密码输入不一致")
            return render(request, 'password.html')
        if not request.user.check_password(old_password):
            messages.success(request, "原密码错误")
            return render(request, 'password.html')

            # 4.更新新密码
        try:
            request.user.set_password(new_password1)
            request.user.save()
        except Exception as e:
            messages.success(request, "修改密码失败")
            return render(request, 'password.html')
            # 5.退出登陆,删除登陆信息
        logout(request)
        # 6.跳转到登陆页面
        response = redirect(reverse('user:login'))

        response.delete_cookie('username')

        return response


class UserIdCardView(LoginRequiredMixin, View):
    def get(self, request):
        id = request.user.Idverification
        if id == "1":
            return redirect(reverse('user:usercenter'))
        if id == "2":
            return redirect(reverse('user:usercenter'))
        return render(request, 'idcard.html')

    def post(self, request):
        # 图片格式
        geshi = ["bmp", "jpg", "png", "tif", "pcx", "tga", "exif", "fpx", "svg", "psd", "cdr", "pcd", "dxf", "ufo",
                 "eps",
                 "ai", "raw", "WMF", "webp"]
        # 判断是否为中文的正则
        regex_str = ".*?([\u4E00-\u9FA5]+).*?"
        user_name = request.POST.get('name')
        user_IDcard = request.POST.get('idcard')
        images = request.FILES.get("images")
        images2 = request.FILES.get("images2")

        if not all([user_name, user_IDcard]):
            messages.success(request, "请输入完整")
            return render(request, 'idcard.html')

        if not all([images, images2]):
            messages.success(request, "请选择图片")
            return render(request, 'idcard.html')

        match_obj = re.findall(regex_str, user_name)
        if not match_obj:
            messages.success(request, "姓名请输入中文")
            return render(request, 'idcard.html')

        idcard = isidcard(user_IDcard)
        if idcard[0] is False:
            messages.success(request, "请输入正确的身份证号")
            return render(request, 'idcard.html')

        if images.name[-3:] not in geshi:
            messages.success(request, "请上传图片")
            return render(request, 'idcard.html')

        if images2.name[-3:] not in geshi:
            messages.success(request, "请上传图片")
            return render(request, 'idcard.html')

        try:
            jiamiID = base64.b64encode(user_IDcard.encode())
            user = User.objects.get(pk=request.user.id)
            user.name = user_name
            user.Idverification = 1
            user.idcard = jiamiID
            user.save()
        except Exception as e:
            messages.success(request, "请重新输入")
            return render(request, 'idcard.html')

        return redirect(reverse('user:usercenter'))


class UserQuestionView(LoginRequiredMixin, View):
    def get(self, request):
        id = request.user.Secret_protection
        if id == "1":
            return redirect(reverse('user:usercenter'))
        return render(request, 'question.html')

    def post(self, request):
        question = request.POST.get("question1")
        question2 = request.POST.get("question2")
        if not all([question, question2]):
            messages.success(request, "密保请填写完整")
            return render(request, 'question.html')
        try:
            user_question1 = base64.b64encode(question.encode())
            user_question2 = base64.b64encode(question2.encode())
            user = User.objects.get(pk=request.user.id)
            user.question1 = user_question1
            user.question2 = user_question2
            user.Secret_protection = 1
            user.save()
        except Exception as e:
            messages.success(request, "密保请重新填写")
            return render(request, 'question.html')
        return redirect(reverse('user:usercenter'))


class UserPhone(LoginRequiredMixin, View):
    def get(self, request):
        phone = request.user.mobile

        # 生成随机验证码
        code = '%06d' % random.randint(0, 999999)

        # redis_conn = get_redis_connection('code')
        #
        # send_sms_flag = redis_conn.get('sms_%s' % phone)
        #
        # if send_sms_flag:
        #     messages.error(request, "发送频繁，请您稍后再来")
        #     return render(request, 'home3.html')

        # 创建连接到redis的对象
        redis_conn = get_redis_connection('code')

        # 保存短信验证码
        redis_conn.setex('sms_%s' % phone, 60, code)

        print("短信验证码》》》》》》》》》》", code)
        # 发送短信
        send_codes(phone, code)

        return render(request, 'bindphone.html')

    def post(self, request):
        yzm1 = request.POST.get('yzm1')
        yzm2 = request.POST.get('yzm2')
        new_phone = request.POST.get('new_phone')

        phone = request.user.mobile

        # 链接redis数据库
        redis_conn = get_redis_connection('code')
        # 查询验证码
        sms_code1 = redis_conn.get('sms_%s' % phone)
        sms_code2 = redis_conn.get('sms_%s' % new_phone)

        print(sms_code1.decode(), sms_code2.decode())

        if phone == new_phone:
            messages.error(request, "不要调皮哦，请输入一个新的手机号")
            return render(request, 'bindphone.html')

        if not all([yzm1, yzm2, new_phone]):
            messages.error(request, "缺少参数")
            return render(request, 'bindphone.html')

        elif yzm1 != sms_code1.decode() or yzm2 != sms_code2.decode():
            messages.error(request, "验证码错误")
            return render(request, 'bindphone.html')

        elif not re.match(r'^1[3-9]\d{9}$', new_phone):
            messages.error(request, "手机号格式错误")
            return render(request, 'bindphone.html')

        # 查询当前用户对应信息
        # user = User.objects.filter(mobile=phone)
        # user.mobile = new_phone
        # user.save()
        try:
            request.user.mobile = new_phone
            request.user.save()
        except:
            messages.error(request, "数据保存失败，请输入一个您自己的手机号")
            return redirect(reverse('user:usercenter'))

        messages.error(request, "操作成功")
        return redirect(reverse('user:usercenter'))


class Bind_phone(View):
    def post(self, request):
        phone = request.POST.get('phone')
        # 生成随机验证码
        code = '%06d' % random.randint(0, 999999)

        # redis_conn = get_redis_connection('code')
        #
        # send_sms_flag = redis_conn.get('sms_%s' % phone)
        #
        # if send_sms_flag:
        #     messages.error(request, "发送频繁，请您稍后再来")
        #     return render(request, 'home3.html')

        # 创建连接到redis的对象
        redis_conn = get_redis_connection('code')

        # 保存短信验证码
        redis_conn.setex('sms_%s' % phone, 60, code)

        print("短信验证码》》》》》》》》》》", code)


class UserEmail(LoginRequiredMixin, View):
    def get(self, request):
        return render(request, 'email.html')

    def post(self, request):
        email = request.POST.get('email_address')
        yzm = request.POST.get('yzm')

        redis_conn = get_redis_connection('code')
        sms_code_saved = redis_conn.get('sms_%s' % email)

        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            messages.error(request, "请输入正确的邮箱")
            return render(request, 'email.html')

        if yzm != sms_code_saved.decode():
            messages.error(request, "验证码错误")
            return render(request, 'email.html')

        # user = User.objects.get(pk=request.user.id)

        request.user.email = email
        request.user.save()

        messages.error(request, "绑定成功")
        return redirect(reverse('user:usercenter'))


class Bind_email(View):
    def post(self, request):
            code = '%06d' % random.randint(0, 999999)
            email = request.POST.get('email')

            if not email:
                data = {
                    'error_info': '请输入一个邮箱'
                }

                return http.JsonResponse(data=data)

            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                data = {
                    'error_info': '邮箱格式错误'
                }

                return http.JsonResponse(data=data)

            try:
                # 发送验证邮件
                msg_Sender = '2730248476@qq.com'  # 发送方邮箱
                msg_code = 'qmwazljrogyndhff'  # 发送方邮箱的授权码
                msg_Receiver = email  # 收件人邮箱

                subject = "爱购物商城"  # 主题
                content = "您的绑定邮箱验证码为:{}".format(code)  # 正文
                msg = MIMEText(content, _charset="utf-8")
                msg['Subject'] = subject
                msg['From'] = msg_Sender
                msg['To'] = msg_Receiver

                s = smtplib.SMTP_SSL("smtp.qq.com", 465)  # 邮件服务器及端口号
                s.login(msg_Sender, msg_code)
                s.sendmail(msg_Sender, msg_Receiver, msg.as_string())
                s.quit()
            except:
                data = {
                    'error_info': '发送失败，请确认您的邮箱是正确的'
                }

                return http.JsonResponse(data=data)

            # 创建连接到redis的对象
            redis_conn = get_redis_connection('code')

            # 保存短信验证码
            redis_conn.setex('sms_%s' % email, 300, code)

            data = {
                'error_info': '发送成功'
            }

            return http.JsonResponse(data=data)


class AddressView(LoginRequiredMixin, View):
    def get(self, request):
        myclient = pymongo.MongoClient("mongodb://localhost:27017/")
        mydb = myclient["dizhi"]
        mycol = mydb["dizhi1"]
        context = []
        for i in mycol.find({"user": request.user.username}):
            context.append(i)
        # print(context)

        return render(request, 'address.html', {'dizhi': context})

    def post(self, request):
        name = request.POST.get('user_name')
        phone = request.POST.get('phone')
        address = request.POST.get('address')

        if not all([name, phone, address]):
            messages.success(request, "新增地址请输入完整")
            return render(request, 'address.html')

        if not re.match(r'^1[3-9]\d{9}$', phone):
            messages.success(request, "手机号输入有误，请重试")
            return render(request, 'address.html')
        myclient = pymongo.MongoClient("mongodb://localhost:27017/")
        mydb = myclient["dizhi"]
        mycol = mydb["dizhi1"]
        mycol.insert_one({"name": name, "phone": phone, "address": address, "user":request.user.username,
                          "weiyi": hash(time.time())})
        messages.success(request, "添加完成")
        return redirect(reverse('user:address'))


class DelAddress(View):
    def get(self,request):
        weiyi = request.GET.get("id")
        myclient = pymongo.MongoClient("mongodb://localhost:27017/")
        mydb = myclient["dizhi"]
        mycol = mydb["dizhi1"]
        myquery = {"weiyi": int(weiyi)}
        mycol.delete_one(myquery)
        return redirect(reverse('user:address'))